#!/usr/bin/env python3

from scapy.all import *
from scapy.layers.dns import DNS, DNSRR, DNSQR
from scapy.layers.http import HTTPRequest
import random

from scapy.layers.inet import UDP, ICMP, TCP, IP

# 禁用Scapy默认的冗余输出
conf.verb = 0

# 目标网站信息
target_url = "blog.csdn.net"
target_path = "/qq_30500575"
target_port = 443  # HTTPS默认端口

# 随机生成源端口（避免被防火墙拦截）
src_port = random.randint(1024, 65535)

def dns_lookup(domain):
    """执行DNS解析获取IP地址"""
    print(f"\n[+] 正在执行DNS查询: {domain}")
    # 构造DNS查询数据包（使用UDP协议）
    dns_pkt = IP(dst="8.8.8.8") / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname=domain))

    # 发送并接收响应（timeout=3秒）
    answer = sr1(dns_pkt, timeout=3)

    if answer and answer.haslayer(DNSRR):
        # 提取所有A记录
        ip_list = [x.rdata for x in answer[DNS].an if x.type == 1]
        print(f"[+] DNS解析结果: {ip_list}")
        return ip_list[0] if ip_list else None  # 直接返回第一个IP地址
    else:
        print("[-] DNS查询失败")
        return None



def icmp_ping(target_ip):
    """ICMP存活检测"""
    print(f"\n[+] 正在发送ICMP ping到 {target_ip}")
    # 构造ICMP Echo Request数据包
    ping_pkt = IP(dst=target_ip) / ICMP()

    # 发送并等待响应
    reply = sr1(ping_pkt, timeout=2)

    if reply:
        print(f"[+] 主机存活！响应来自: {reply.src}")
        return True
    else:
        print("[-] 主机无响应")
        return False


def tcp_port_scan(target_ip, ports):
    """TCP端口扫描"""
    print(f"\n[+] 正在扫描 {target_ip} 的TCP端口")

    for port in ports:
        # 构造SYN数据包（flags='S'表示SYN）
        syn_pkt = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='S')

        # 发送并接收响应
        response = sr1(syn_pkt, timeout=1)

        if response:
            # 检查TCP flags
            if response.haslayer(TCP):
                flags = response.getlayer(TCP).flags
                # SYN-ACK响应（0x12）表示端口开放
                if flags == 0x12:
                    print(f"[*] 端口 {port} 开放")
                    # 发送RST关闭连接
                    rst_pkt = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='R')
                    send(rst_pkt)
                elif flags == 0x14:
                    print(f"[*] 端口 {port} 关闭")
                else:
                    print(f"[*] 端口 {port} 响应异常（Flags: {flags})")
        else:
            print(f"[-] 端口 {port} 无响应")


def http_interaction(target_ip, port):
    """尝试HTTP交互（注意HTTPS需要TLS处理）"""
    print(f"\n[+] 尝试与 {target_ip}:{port} 建立TCP连接")

    # 构造SYN数据包
    syn = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='S')
    syn_ack = sr1(syn, timeout=2)

    if syn_ack and syn_ack.haslayer(TCP) and syn_ack[TCP].flags == 0x12:
        print("[+] 收到SYN-ACK，发送ACK完成三次握手")
        ack = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='A',
                                      seq=syn_ack[TCP].ack, ack=syn_ack[TCP].seq + 1)
        send(ack)

        # 构造HTTP GET请求
        http_get = (
            "GET {} HTTP/1.1\r\n"
            "Host: {}\r\n"
            "User-Agent: Scapy Test Client\r\n"
            "\r\n"
        ).format(target_path, target_url).encode()

        # 发送HTTP请求
        request = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='PA') / Raw(load=http_get)
        reply = sr1(request, timeout=3)

        if reply:
            print("[+] 收到HTTP响应：")
            print(reply.show())
        else:
            print("[-] 未收到HTTP响应")

        # 发送FIN关闭连接
        fin = IP(dst=target_ip) / TCP(sport=src_port, dport=port, flags='FA')
        send(fin)
    else:
        print("[-] TCP连接失败")


def traceroute(target_ip):
    """路由跟踪实现"""
    print(f"\n[+] 正在追踪到 {target_ip} 的路由路径")
    # 设置初始TTL
    for ttl in range(1, 30):
        # 构造ICMP数据包并递增TTL
        pkt = IP(dst=target_ip, ttl=ttl) / ICMP()
        reply = sr1(pkt, timeout=2, verbose=0)

        if reply is None:
            print(f"{ttl}: *")
        elif reply.type == 0:  # ICMP Echo Reply
            print(f"{ttl} {reply.src}  到达目标！")
            break
        else:
            print(f"{ttl} {reply.src}")

            # 如果到达目标则终止
        if reply and reply.src == target_ip:
            break


if __name__ == "__main__":
    # 解析目标域名
    target_ip = dns_lookup(target_url)

    if target_ip:
        # ICMP存活检测
        if icmp_ping(target_ip):
            # TCP端口扫描（常见端口）
            tcp_port_scan(target_ip, [80, 443, 8080])

            # 尝试HTTP交互（注意实际是HTTPS）
            http_interaction(target_ip, target_port)

            # 执行路由跟踪
            traceroute(target_ip)

            # 嗅探流量（持续3秒）
            print("\n[+] 开始嗅探本地流量（持续3秒）")
            sniff(filter=f"host {target_ip}", prn=lambda x: x.summary(), timeout=3)